using System;
using System.Threading;
using Catastrophe.AutoSulution.TaskM;
using Catastrophe.Common.ObjM;

namespace Catastrophe.AutoSulution.TimeCal
{
	public class AnalyzeProTime
	{
		private readonly ProTimeInfo _onLineTimeInfo = new ProTimeInfo();

		private readonly ProTimeInfo _startTimeInfo = new ProTimeInfo();

		private readonly ProTimeInfo _stopTimeInfo = new ProTimeInfo();

		private readonly ProTimeInfo _resetTimeInfo = new ProTimeInfo();

		private readonly ProTimeInfo _breakTimeInfo = new ProTimeInfo();

		private readonly ProTimeInfo _waitTimeInfo = new ProTimeInfo();

		private readonly ProTimeInfo _cancelTimeInfo = new ProTimeInfo();

		/// <summary>
		///     开始工作时间点
		/// </summary>
		public DateTime StartTimePoint;

		public DateTime EndTimePoint;

		/// <summary>
		///     判断数据是否发生变化对象
		/// </summary>
		private readonly ControlLogic<int> _controlLogic0 = new ControlLogic<int>();

		private readonly ControlLogic<bool> _controlLogic1 = new ControlLogic<bool>();

		/// <summary>
		/// 任务
		/// </summary>
		private TaskManager _taskManager;

		/// <summary>
		/// 生产状态
		/// </summary>
		private ProStateEnum _proState = ProStateEnum.UnKnow;

		private int _uniqueId = -1;

		/// <summary>
		/// 统计次数发生变化
		/// </summary>
		public Action<ProStateEnum, long> TimesChangedHandler;

		/// <summary>
		/// 中断时间
		/// </summary>
		public string BreakTimeFormat => this._breakTimeInfo.SumTimeFormat;

		public double BreakTime => this._breakTimeInfo.SumTime;

		/// <summary>
		/// 复位时间
		/// </summary>
		public string ResetTimeFormat => this._resetTimeInfo.SumTimeFormat;

		public double ResetTime => this._resetTimeInfo.SumTime;

		/// <summary>
		/// 在线总时间格式化0:0:0:0
		/// </summary>
		public string OnlineTimeFormat => this._onLineTimeInfo.SumTimeFormat;

		public double OnlineTime => this._onLineTimeInfo.SumTime;

		/// <summary>
		///     开始总时间格式化0:0:0:0
		/// </summary>
		public string RunTimeFormat => this._startTimeInfo.SumTimeFormat;

		public double RunTime => this._startTimeInfo.SumTime;

		/// <summary>
		///     等待总时间格式化0:0:0:0
		/// </summary>
		public string WaitTimeFormat => this._waitTimeInfo.SumTimeFormat;

		public double WaitTime => this._waitTimeInfo.SumTime;

		/// <summary>
		///    停止总时间格式化
		/// </summary>
		public string StopTimeFormat => this._stopTimeInfo.SumTimeFormat;

		public double StopTime => this._stopTimeInfo.SumTime;

		/// <summary>
		///    取消总时间格式化
		/// </summary>
		public string CancelTimeFormat => this._cancelTimeInfo.SumTimeFormat;

		public double CancelTime => this._cancelTimeInfo.SumTime;

		/// <summary>
		///     在线状态
		/// </summary>
		public bool IsOneLine { get; set; }

		public ProStateEnum ProState
		{
			get
			{
				return this._proState;
			}
			set
			{
				this._proState = ((!this.IsOneLine) ? ProStateEnum.UnKnow : value);
			}
		}

		/// 次数相关
		public long OnLineTimes { get; set; }

		public long OffLineTimes { get; set; }

		public long StartTimes { get; set; }

		public long StopTimes { get; set; }

		public long ResetTimes { get; set; }

		public long BreakTimes { get; set; }

		public long WaitTimes { get; set; }

		public long CancelTimes { get; set; }

		/// <summary>
		///     开始作业初始化
		/// </summary>
		public void CalRunTime()
		{
			if (this._taskManager == null)
			{
				this._taskManager = new TaskManager
				{
					SaveTask = true
				};
				this._taskManager.Start(CalOnlineTime, isRunTime: true, this._startTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(CalStartTime, isRunTime: true, this._startTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(CalStopTime, isRunTime: true, this._stopTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(CalResetTime, isRunTime: true, this._resetTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(CalBreakTime, isRunTime: true, this._breakTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(CalWaitTime, isRunTime: true, this._waitTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(CalCancelTime, isRunTime: true, this._cancelTimeInfo.SleepTime, immediateExcute: false);
				this._taskManager.Start(TastStateManager, 10);
			}
		}

		/// <summary>
		/// 初始化从当前时间开始计时
		/// </summary>
		public void TimeIni()
		{
			this.StartTimePoint = DateTime.Now;
			this._onLineTimeInfo.Clear();
			this._onLineTimeInfo.Clear();
			this._startTimeInfo.Clear();
			this._stopTimeInfo.Clear();
			this._resetTimeInfo.Clear();
			this._breakTimeInfo.Clear();
			this._waitTimeInfo.Clear();
			this._cancelTimeInfo.Clear();
		}

		/// <summary>
		/// 监控状态标识
		/// </summary>
		private void CheckProState()
		{
			long arg = 0L;
			switch (this._proState)
			{
			case ProStateEnum.Start:
				this.StartTimes++;
				arg = this.StartTimes;
				this._taskManager.ManualReset(CalStartTime, pause: false);
				break;
			case ProStateEnum.Stop:
				this.StopTimes++;
				arg = this.StopTimes;
				this._taskManager.ManualReset(CalStopTime, pause: false);
				break;
			case ProStateEnum.Reset:
				this.ResetTimes++;
				arg = this.ResetTimes;
				this._taskManager.ManualReset(CalResetTime, pause: false);
				break;
			case ProStateEnum.Break:
				this.BreakTimes++;
				arg = this.BreakTimes;
				this._taskManager.ManualReset(CalBreakTime, pause: false);
				break;
			case ProStateEnum.Wait:
				this.WaitTimes++;
				arg = this.WaitTimes;
				this._taskManager.ManualReset(CalWaitTime, pause: false);
				break;
			case ProStateEnum.Cancel:
				this.CancelTimes++;
				arg = this.CancelTimes;
				this._taskManager.ManualReset(CalCancelTime, pause: false);
				break;
			}
			try
			{
				this.TimesChangedHandler?.Invoke(this._proState, arg);
			}
			catch (Exception)
			{
			}
		}

		/// <summary>
		/// 暂停
		/// </summary>
		/// <param name="act"></param>
		private void TastReset(Action act = null)
		{
			if (act != new Action(CalStartTime))
			{
				this._taskManager.ManualReset(CalStartTime);
			}
			if (act != new Action(CalStopTime))
			{
				this._taskManager.ManualReset(CalStopTime);
			}
			if (act != new Action(CalResetTime))
			{
				this._taskManager.ManualReset(CalResetTime);
			}
			if (act != new Action(CalBreakTime))
			{
				this._taskManager.ManualReset(CalBreakTime);
			}
			if (act != new Action(CalWaitTime))
			{
				this._taskManager.ManualReset(CalWaitTime);
			}
			if (act != new Action(CalCancelTime))
			{
				this._taskManager.ManualReset(CalCancelTime);
			}
		}

		/// <summary>
		/// 监控状态标识任务
		/// </summary>
		private void TastStateManager()
		{
			if (this._controlLogic0.IsDataChange((int)this._proState) && this.IsOneLine)
			{
				this.CheckProState();
			}
			if (this._controlLogic1.IsDataChange(this.IsOneLine))
			{
				this._taskManager.ManualReset(CalOnlineTime, !this.IsOneLine);
				if (!this.IsOneLine)
				{
					this.OffLineTimes++;
					this._onLineTimeInfo.LastTime += this._onLineTimeInfo.NowTime;
					this.TastReset();
					this._uniqueId = -1;
					this._proState = ProStateEnum.UnKnow;
					this.EndTimePoint = DateTime.Now;
				}
				else
				{
					this.OnLineTimes++;
					this.StartTimePoint = DateTime.Now;
				}
			}
		}

		/// <summary>
		/// 运行时间
		/// </summary>
		private void CalOnlineTime()
		{
			this._onLineTimeInfo.NowTime = TimeHelper.TimeDecFormat(this.StartTimePoint, DateTime.Now);
			this._onLineTimeInfo.SumTime = this._onLineTimeInfo.LastTime + this._onLineTimeInfo.NowTime;
		}

		/// <summary>
		/// 计算开始时间
		/// </summary>
		private void CalStartTime()
		{
			this.CalTime(Thread.CurrentThread.ManagedThreadId, ref this._startTimeInfo.SumTime, ref this._startTimeInfo.LastTime, ref this._startTimeInfo.NowTime, ref this._startTimeInfo.BreakTime, this._startTimeInfo.DelayTime, CalStartTime);
		}

		/// <summary>
		/// 计算停止时间
		/// </summary>
		private void CalStopTime()
		{
			this.CalTime(Thread.CurrentThread.ManagedThreadId, ref this._stopTimeInfo.SumTime, ref this._stopTimeInfo.LastTime, ref this._stopTimeInfo.NowTime, ref this._stopTimeInfo.BreakTime, this._stopTimeInfo.DelayTime, CalStopTime);
		}

		/// <summary>
		/// 计算复位时间
		/// </summary>
		private void CalResetTime()
		{
			this.CalTime(Thread.CurrentThread.ManagedThreadId, ref this._resetTimeInfo.SumTime, ref this._resetTimeInfo.LastTime, ref this._resetTimeInfo.NowTime, ref this._resetTimeInfo.BreakTime, this._resetTimeInfo.DelayTime, CalResetTime);
		}

		/// <summary>
		/// 计算中断时间
		/// </summary>
		private void CalBreakTime()
		{
			this.CalTime(Thread.CurrentThread.ManagedThreadId, ref this._breakTimeInfo.SumTime, ref this._breakTimeInfo.LastTime, ref this._breakTimeInfo.NowTime, ref this._breakTimeInfo.BreakTime, this._breakTimeInfo.DelayTime, CalBreakTime);
		}

		/// <summary>
		/// 计算等待时间
		/// </summary>
		private void CalWaitTime()
		{
			this.CalTime(Thread.CurrentThread.ManagedThreadId, ref this._waitTimeInfo.SumTime, ref this._waitTimeInfo.LastTime, ref this._waitTimeInfo.NowTime, ref this._waitTimeInfo.BreakTime, this._waitTimeInfo.DelayTime, CalWaitTime);
		}

		/// <summary>
		/// 计算取消时间
		/// </summary>
		private void CalCancelTime()
		{
			this.CalTime(Thread.CurrentThread.ManagedThreadId, ref this._cancelTimeInfo.SumTime, ref this._cancelTimeInfo.LastTime, ref this._cancelTimeInfo.NowTime, ref this._cancelTimeInfo.BreakTime, this._cancelTimeInfo.DelayTime, CalCancelTime);
		}

		/// <summary>
		/// 计算时间
		/// </summary>
		/// <param name="currentId"></param>
		/// <param name="sumTime"></param>
		/// <param name="lastTime"></param>
		/// <param name="nowTime"></param>
		/// <param name="breakTime"></param>
		/// <param name="delayTime"></param>
		/// <param name="act"></param>
		private void CalTime(int currentId, ref double sumTime, ref double lastTime, ref double nowTime, ref DateTime? breakTime, int delayTime, Action act)
		{
			try
			{
				if (Interlocked.CompareExchange(ref this._uniqueId, -2, currentId) == this._uniqueId)
				{
					lastTime += nowTime;
					if (delayTime > 0)
					{
						Thread.Sleep(delayTime * 1000);
					}
					this.TastReset(act);
					breakTime = DateTime.Now;
				}
				DateTime? dateTime = breakTime;
				if (dateTime.HasValue)
				{
					nowTime = TimeHelper.TimeDecFormat(dateTime.Value, DateTime.Now);
					sumTime = lastTime + nowTime;
					this._uniqueId = currentId;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
		}

		/// <summary>
		/// 清空初始化
		/// </summary>
		public void Clear()
		{
			this._onLineTimeInfo.Clear();
			this._startTimeInfo.Clear();
			this._stopTimeInfo.Clear();
			this._resetTimeInfo.Clear();
			this._breakTimeInfo.Clear();
			this._waitTimeInfo.Clear();
			this._cancelTimeInfo.Clear();
		}
	}
}
